package kt.smpp.observer;

import ie.omk.smpp.Connection;
import ie.omk.smpp.event.ReceiverExitEvent;
import ie.omk.smpp.event.SMPPEventAdapter;
import ie.omk.smpp.message.BindResp;
import ie.omk.smpp.message.DeliverSM;
import ie.omk.smpp.message.EnquireLink;
import ie.omk.smpp.message.EnquireLinkResp;
import ie.omk.smpp.message.SMPPPacket;
import ie.omk.smpp.message.SubmitSMResp;
import ie.omk.smpp.message.Unbind;
import ie.omk.smpp.message.UnbindResp;

import java.io.IOException;
import java.sql.SQLException;
import java.util.Calendar;

import kt.GWConfig;
import kt.dal.DAL;
import kt.smpp.pdu.SMSRequest;
import kt.smpp.pdu.SMSResponse;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

public class AsyncObserver extends SMPPEventAdapter {
	
	private static Logger logger = LogManager.getLogger(AsyncObserver.class);

	public AsyncObserver() {
	}

	// Handle message delivery. This method does not need to acknowledge the
	// deliver_sm message as we set the Connection object to
	// automatically acknowledge them.
	public void deliverSM(Connection source, DeliverSM dm) {
		int st = dm.getCommandStatus();

		if (st != 0) {
			logger.info("DeliverSM: !Error! status = " + st);
		} else {
			if(logger.isInfoEnabled())
				logger.info("DeliverSM: \"" + dm.toString() + "\"");
			System.out.println("DeliverSM: \"" + dm.toString() + "\"");
			SMSRequest req = new SMSRequest(dm, GWConfig.parameters.operator);
			DAL.saveMO(req);
			//TODO: xu ly MO luon, khong can luu trong mot so truong hop
/*
			if(req.getServiceNumber().equalsIgnoreCase("1941")) {
				logger.info("service number is 1941, process, not save to MO");
				if(req.getInfo().startsWith("H") || req.getInfo().startsWith("h") 
						|| req.getInfo().equalsIgnoreCase("1") || req.getInfo().equalsIgnoreCase("ON")
						|| req.getInfo().equalsIgnoreCase("0") || req.getInfo().equalsIgnoreCase("OFF")){
					// luu vao pending request
					DAL.savePendingRequest(req, "DNEWS");
				} else {
					String invalidContent = "Syntax error, Please send HELP to 1941 for more information of DailyNews or call 1941 to listen hot and latest news. Help: 109. Thanks!";
					DAL.saveMTtoQueue(req.getSenderNumber(), invalidContent, req.getServiceNumber(), req.getMobileOperator());
				}
				DAL.logMO(req);
			} else if(req.getServiceNumber().equalsIgnoreCase("1945")) {
				logger.info("service number is 1945, process, not save to MO");
				if(req.getInfo().startsWith("H") || req.getInfo().startsWith("h") 
						|| req.getInfo().equalsIgnoreCase("1") || req.getInfo().equalsIgnoreCase("ON")
						|| req.getInfo().equalsIgnoreCase("0") || req.getInfo().equalsIgnoreCase("OFF")){
					// luu vao pending request
					DAL.savePendingRequest(req, "SBOX");
				} else {
					String invalidContent = "Syntax error, Please send HELP to 1945 for more information of Story Box or call 1945 to listen exciting stories. Help: 109. Thanks!";
					DAL.saveMTtoQueue(req.getSenderNumber(), invalidContent, req.getServiceNumber(), req.getMobileOperator());
				}
				DAL.logMO(req);
			} else {
				DAL.saveMO(req);
			}
			
//*/
		}
	}

	// Called when a bind response packet is received.
	public void bindResponse(Connection source, BindResp br) {
		if (br.getCommandStatus() == 0) {
			logger.info("Successfully bound. Awaiting messages..");
		} else {
			logger.info("Bind did not succeed!");
			try {
				source.closeLink();
			} catch (IOException x) {
				logger.info("IOException closing link:\n" + x);
			}
		}
	}

	// This method is called when the SMSC sends an unbind request to our
	// receiver. We must acknowledge it and terminate gracefully..
	public void unbind(Connection source, Unbind ubd) {
		logger.info("SMSC requested unbind. Acknowledging..");
		try {
			// SMSC requests unbind..
			UnbindResp ubr = new UnbindResp(ubd);
			source.sendResponse(ubr);
		} catch (IOException x) {
			logger.info("IOException while acking unbind: " + x.toString());
		}
	}

	// This method is called when the SMSC responds to an unbind request we
	// sent to it..it signals that we can shut down the network connection and
	// terminate our application..
	public void unbindResponse(Connection source, UnbindResp ubr) {
		int st = ubr.getCommandStatus();

		if (st != 0) {
			logger.info("Unbind response: !Error! status = " + st);
		} else {
			logger.info("Successfully unbound.");
		}
	}

	// this method is called when the receiver thread is exiting normally.
	public void receiverExit(Connection source, ReceiverExitEvent ev) {
		if (ev.getReason() == ReceiverExitEvent.BIND_TIMEOUT) {
			logger.info("Bind timed out waiting for response.");
		}
		
		try {
			logger.info("Close the SMSC link because Receiver thread exited");
			source.closeLink();
		} catch (IOException x) {
			logger.info("IOException closing link:\n" + x);
		}
	}

	// this method is called when the receiver thread exits due to an
	// exception in the thread...
	public void receiverExitException(Connection source,
			ReceiverExitEvent ev) {
		logger.fatal("Receiver thread exited abnormally. The following exception was thrown:\n", ev.getException());
		try {
			logger.info("Close the SMSC link because Receiver thread exited ABNORMALLY");
			source.closeLink();
		} catch (IOException x) {
			logger.info("IOException closing link:\n" + x);
		}
	}

	/**
	 * EnquireLink packet received from the SMSC.
	 */
	@Override
	public void queryLink(Connection source, EnquireLink el) {
		String msg =el.getMessageText(); 
		logger.info(msg);
		System.out.println("" + Calendar.getInstance().getTime().toString() + " queryLink " + msg);
	}
	
	/**
	 * EnquireLink response packet received from the SMSC.
	 */
	@Override
	public void queryLinkResponse(Connection source, EnquireLinkResp elr) {
		logger.info(elr.getMessageText());			
	}

	@Override
	public void unidentified(Connection source, SMPPPacket pak) {
		logger.info("unknowed package from SMSC:" + pak.getMessageText());
	}

	/**
	 * EnquireLink response packet received from the SMSC.
	 */
	@Override
	public void submitSMResponse(Connection source, SubmitSMResp smr) {
		int seqNo = smr.getSequenceNum();
		if (smr.getCommandStatus() != 0) {
			logger.info("Message was not submitted. Error code: " + smr.getCommandStatus() + "; Seq No: " + seqNo);
			submitMsgResult(seqNo, false);
		} else {
			logger.info("Message Submitted! SequenceNum = " + smr.getSequenceNum());
			submitMsgResult(seqNo, true);
		}
	}
	
	private void submitMsgResult(int seqNo, boolean isSuccessfull)  {
		//java.sql.Connection sqlCnn = null;
		try {
			//sqlCnn = DAL.getCnn();
			if (isSuccessfull) {
				//sqlCnn.setAutoCommit(false);
				DAL.logMT(seqNo);
				DAL.deleteMT(seqNo);
				//sqlCnn.commit();
			} else {
				DAL.updateMTStatus(seqNo, SMSResponse.DeliveryStatus.SentFail);
			}
		} catch (SQLException e) {
			logger.error("Error accessing DB", e);
			//DAL.rollBack();
		}
	}
}
